package com.demo.common.redis.expire;

import cn.hutool.extra.spring.SpringUtil;
import com.demo.common.constants.CommonConstants;
import com.demo.common.redis.constants.RedisKeyExpiration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 消息过期监听
 * @author molong
 * @date 2022/6/22
 */
public class RedisExpiredListener implements MessageListener {

    private Logger logger = LoggerFactory.getLogger(RedisExpiredListener.class);

    private static Map<String,BaseRedisExpired> map = new HashMap<>();

    @Override
    public void onMessage(Message message, byte[] bytes) {
        byte[] body = message.getBody();
        byte[] channel = message.getChannel();
        String key = new String(body);
        if(!key.startsWith(RedisKeyExpiration.SYSTEM_EXPIRE)){
            return;
        }
        logger.info(" "+ String.format("onMessage >> channel: %s, body: %s, bytes: %s",new String(channel),new String(body),new String(bytes)));
        String[] str = key.split(":");
        String exKey = RedisKeyExpiration.SYSTEM_EXPIRE+str[1] + ":";
        BaseRedisExpired gsrfgwerg = map.get(exKey);
        if(Objects.isNull(gsrfgwerg)){
            gsrfgwerg = getExpireKey(exKey);
            if(Objects.isNull(gsrfgwerg)){
                logger.error("redis key 过期事件,未找到对应的实现方法:key={}",key);
                return;
            }
        }
        String msg = key.replace(exKey,"");
        if(existing(msg)){
            gsrfgwerg.handle(msg);
        }
    }

    private BaseRedisExpired getExpireKey(String key){
        for (BaseRedisExpired value : SpringUtil.getBeansOfType(BaseRedisExpired.class).values()) {
            String expireKey = value.setExpireKey();
            expireKey = RedisKeyExpiration.SYSTEM_EXPIRE + expireKey;
            if(expireKey.equals(key)){
                map.put(key,value);
                return value;
            }
        }
        return null;
    }

    private boolean existing(String key){
        key = RedisKeyExpiration.REDIS_LOCK_EXPIRE + key;
        RedisTemplate redisTemplate = SpringUtil.getBean(StringRedisTemplate.class);
        boolean existing = redisTemplate.opsForValue().setIfAbsent(key, CommonConstants.LOCK_EXPIRE_VALUE);
        redisTemplate.expire(key, CommonConstants.LOCK_EXPIRE_TIME_OUT, TimeUnit.SECONDS);
        return existing;
    }


}
